package com.appsindy.common.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

public class DateUtils {
    public static final String id = "$RCSfile: DateUtil.java,v $ $Revision: 975 $ $Date: 2009-11-05 11:27:19 +0700 (Thu, 05 Nov 2009) $ $State: Exp $";

    public static final SimpleDateFormat dFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.US);
    public static final SimpleDateFormat dtFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.US);
    public static final SimpleDateFormat timeStampFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss.SSS", Locale.US);
    public static final SimpleDateFormat hFormat = new SimpleDateFormat("HH", Locale.US);
    public static final SimpleDateFormat mFormat = new SimpleDateFormat("mm", Locale.US);
    
    public static final SimpleDateFormat sqldFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
    public static final SimpleDateFormat sqlDtFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
    
    public static final SimpleDateFormat genmsgtrxFormat = new SimpleDateFormat("ddMMyyHHmmss", Locale.US);
    public static final SimpleDateFormat mysqlDateTimeFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
    
    public static final Calendar MIN_DATE = getCalendar(Calendar.getInstance(Locale.US), "30/12/1899 00:00", dtFormat);

    private static final String WEEK_TH = "สัปดาห์";
    private static final String WEEK_EN = "Week";

    private static final String[] MONTH_TH = {"ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."};
    private static final String[] MONTH_EN = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

   
    private DateUtils() {
    }

    public static String getDateStr(Date date, boolean isTH) {
        if (date == null) {
            return "";
        } else {
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(date);
            if (isTH)
                cal.add(Calendar.YEAR, 543);

            return dFormat.format(cal.getTime());
        }
    }

    public static String getDateTimeStr(Date date, boolean isTH) {
        if (date == null) {
            return "";
        } else {
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(date);
            if (isTH)
                cal.add(Calendar.YEAR, 543);

            return dtFormat.format(cal.getTime());
        }
    }

    public static String getDateTimeStampStr(Date date, boolean isTH) {
        if (date == null) {
            return "";
        } else {
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(date);
            if (isTH)
                cal.add(Calendar.YEAR, 543);

            return timeStampFormat.format(cal.getTime());
        }
    }

    public static String getHourStr(Date date) {
        if (date == null) {
            return "";
        } else {
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(date);

            return hFormat.format(cal.getTime());
        }
    }

    public static String getMinuteStr(Date date) {
        if (date == null) {
            return "";
        } else {
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(date);

            return mFormat.format(cal.getTime());
        }
    }

    public static String getSqlDateStr(Date date) {
        if (date == null) {
            return "";
        } else {
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(date);

            return sqldFormat.format(cal.getTime());
        }
    }

    public static String getSqlDateEndStr(Date date) {
        if (date == null) {
            return "";
        } else {
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(date);

            return sqldFormat.format(cal.getTime()) + " 23:59:59.999";
        }
    }

    public static String getSqlWeekStr(String week, boolean isTH) {
        // Week ww, yyyy -> yyyy, ww
        String[] ss = StringUtils.toArrayString(week, " ");
        if (ss != null && ss.length == 3) {
            String w = StringUtils.toString(ss[1]).replaceAll(",", "");
            String y = getSqlYearStr(StringUtils.toString(ss[2]), isTH);
            return y + ", " + w;
        }
        return "";
    }

    public static String getSqlMonthStr(String month, boolean isTH) {
        // mm, yyyy -> yyyy, mm
        String[] ss = StringUtils.toArrayString(month, " ");
        if (ss != null && ss.length == 2) {
            String m = StringUtils.toString(ss[0]).replaceAll(",", "");
            String y = getSqlYearStr(StringUtils.toString(ss[1]), isTH);
            return y + ", " + m;
        }
        return "";
    }

    public static String getSqlQuarterStr(String quarter, boolean isTH) {
        // q, yyyy -> yyyy, q
        String[] ss = StringUtils.toArrayString(quarter, " ");
        if (ss != null && ss.length == 2) {
            String q = StringUtils.toString(ss[0]).replaceAll(",", "");
            String y = getSqlYearStr(StringUtils.toString(ss[1]), isTH);
            return y + ", " + q;
        }
        return "";
    }

    public static String getSqlYearStr(String year, boolean isTH) {
        // yyyy -> yyyy
        int y = StringUtils.toInt(year);
        if (y > 0) {
            if (isTH)
                y -= 543;
            return y + "";
        }
        return "";
    }

    public static String getWeekStr(String week, boolean isTH) {
        // yyyy, ww -> Week ww, yyyy
        String[] ss = StringUtils.toArrayString(week, " ");
        if (ss != null && ss.length == 2) {
            String y = getYearStr(StringUtils.toString(ss[0]).replaceAll(",", ""), isTH);
            String w = StringUtils.toString(ss[1]);
            if (isTH)
                return WEEK_TH + " " + w + ", " + y;
            else
                return WEEK_EN + " " + w + ", " + y;
        }
        return "";
    }

    public static String getMonthStr(String month, boolean isTH) {
        // yyyy, mm -> MMM-yyyy
        String[] ss = StringUtils.toArrayString(month, " ");
        if (ss != null && ss.length == 2) {
            String y = getYearStr(StringUtils.toString(ss[0]).replaceAll(",", ""), isTH);
            int m = StringUtils.toInt(ss[1]);
            if (m > 0 && m <= MONTH_EN.length) {
                if (isTH)
                    return MONTH_TH[m - 1] + "-" + y;
                else
                    return MONTH_EN[m - 1] + "-" + y;
            }
        }
        return "";
    }

    public static String getQuarterStr(String quarter, boolean isTH) {
        // yyyy, q -> MMM-MMM, yyyy
        String[] ss = StringUtils.toArrayString(quarter, " ");
        if (ss != null && ss.length == 2) {
            String y = getYearStr(StringUtils.toString(ss[0]).replaceAll(",", ""), isTH);
            int q = StringUtils.toInt(ss[1]);
            if (q > 0 && q <= 4) {
                if (isTH)
                    return MONTH_TH[(q - 1) * 3] + "-" + MONTH_TH[(q * 3) - 1] + ", " + y;
                else
                    return MONTH_EN[(q - 1) * 3] + "-" + MONTH_EN[(q * 3) - 1] + ", " + y;
            }
        }
        return "";
    }

    public static String getYearStr(String year, boolean isTH) {
        // yyyy -> yyyy
        int y = StringUtils.toInt(year);
        if (y > 0) {
            if (isTH)
                y += 543;
            return y + "";
        }
        return "";
    }

    public static Date createDate(String strDate, boolean isTH) {
        if (StringUtils.isEmpty(strDate) || strDate.length() < 10) {
            return null;
        }

        int dd = StringUtils.toInt(strDate.substring(0, 2));
        int mm = StringUtils.toInt(strDate.substring(3, 5));
        int yyyy = StringUtils.toInt(strDate.substring(6, 10));

        return createDate(dd, mm, yyyy, isTH);
    }

    public static Date createDate(int dd, int mm, int yyyy, boolean isTH) {
        if (dd <= 0 || mm <= 0 || yyyy <= 0) {
            return null;
        }

        Calendar cal = Calendar.getInstance(Locale.US);
        if (isTH)
            cal.set(yyyy - 543, mm - 1, dd, 0, 0, 0);
        else
            cal.set(yyyy, mm - 1, dd, 0, 0, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    public static Date createDateTime(String strDateTime, boolean isTH) {
        Calendar c = null;
        if(isTH) c = Calendar.getInstance(new Locale("th", "TH"));
        else c = Calendar.getInstance(Locale.US);
        Date d = new Date();
        try {
            d = dtFormat.parse(strDateTime);
            //d = sqlDtFormat.parse(strDateTime);
        } catch (ParseException ex) {
            ex.printStackTrace();
        }
        return d;
    }
    
    public static Date createDateTime(String strDate, String hour, String minute, boolean isTH) {
        if (StringUtils.isEmpty(strDate) || strDate.length() < 10) {
            return null;
        }

        int dd = StringUtils.toInt(strDate.substring(0, 2));
        int mm = StringUtils.toInt(strDate.substring(3, 5));
        int yyyy = StringUtils.toInt(strDate.substring(6, 10));
        int h = StringUtils.toInt(hour);
        int m = StringUtils.toInt(minute);

        if (dd <= 0 || mm <= 0 || yyyy <= 0) {
            return null;
        }

        Calendar cal = Calendar.getInstance(Locale.US);
        if (isTH)
            cal.set(yyyy - 543, mm - 1, dd, h, m, 0);
        else
            cal.set(yyyy, mm - 1, dd, h, m, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }
    
    public static Date createDateTimeTo(String strDate, String hour, String minute, boolean isTH) {
        if (StringUtils.isEmpty(strDate) || strDate.length() < 10) {
            return null;
        }

        int dd = StringUtils.toInt(strDate.substring(0, 2));
        int mm = StringUtils.toInt(strDate.substring(3, 5));
        int yyyy = StringUtils.toInt(strDate.substring(6, 10));
        int h = StringUtils.toInt(hour);
        int m = StringUtils.toInt(minute);

        if (dd <= 0 || mm <= 0 || yyyy <= 0) {
            return null;
        }

        Calendar cal = Calendar.getInstance(Locale.US);
        if (isTH)
            cal.set(yyyy - 543, mm - 1, dd, h, m, 59);
        else
            cal.set(yyyy, mm - 1, dd, h, m, 59);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    public static Date createTime(String hour, String minute) {
        int dd = 1;
        int mm = 1;
        int yyyy = 1900;
        int h = StringUtils.toInt(hour);
        int m = StringUtils.toInt(minute);

        Calendar cal = Calendar.getInstance(Locale.US);
        cal.set(yyyy, mm - 1, dd, h, m, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    public static int getDate(Date d) {
        if (d == null) {
            return 0;
        }
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        return cal.get(Calendar.DATE);
    }

    public static int getMonth(Date d) {
        if (d == null) {
            return 0;
        }
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        return cal.get(Calendar.MONTH) + 1;
    }

    public static int getYear(Date d) {
        if (d == null) {
            return 0;
        }
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        return cal.get(Calendar.YEAR);
    }

    public static Date setYear(Date d, int year) {
        if (d == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        cal.set(Calendar.YEAR, year);
        //d.setYear(cal.getTime().getYear());
        return cal.getTime();
    }

    public static int getHour(Date d) {
        if (d == null) {
            return 0;
        }
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        return cal.get(Calendar.HOUR);
    }

    public static Date setHour(Date d, int hour) {
        if (d == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        cal.set(Calendar.HOUR, hour);
        //d.setHours(cal.getTime().getHours());
        return cal.getTime();
    }

    public static int getMinute(Date d) {
        if (d == null) {
            return 0;
        }
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        return cal.get(Calendar.MINUTE);
    }

    public static Date setMinute(Date d, int min) {
        if (d == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        cal.set(Calendar.MINUTE, min);
        //d.setMinutes(cal.getTime().getMinutes());
        return cal.getTime();
    }

    public static Date trimDate(Date d) {
        if (d != null) {
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(d);

            cal.set(Calendar.HOUR, 0);
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            cal.set(Calendar.MILLISECOND, 0);

            return cal.getTime();
        }
        return null;
    }
    
    public static boolean isDateEqual(Date date1, Date date2){
        if(date1 != null && date2 != null && DateUtils.trimDate(date1).equals(DateUtils.trimDate(date2))){
            return true;
        }
        return false;
    }

    public static Calendar getCalendar(Calendar cal, String dateString, SimpleDateFormat oDateFormat) {
        return getCalendar(cal, dateString, oDateFormat, MIN_DATE);
    }

    public static Calendar getCalendar(Calendar cal, String dateString, SimpleDateFormat oDateFormat, Calendar _default) {
        Calendar oCalendar = cal;
        if (oCalendar == null)
            oCalendar = _default;
        oDateFormat = dtFormat;

        try {
            oCalendar.setTime(oDateFormat.parse(dateString));
        }
        catch (Exception e) {
            if (_default == null) {
                oCalendar = null;
            } else {
                oCalendar.setTime(_default.getTime());
            }
        }
        return oCalendar;
    }

    public static Date addDate(Date date, int dateAdd) {
        Calendar cal;
        if (date == null) {
            return null;
        } else {
            cal = Calendar.getInstance();
            cal.setTime(date);
            cal.add(Calendar.DATE, dateAdd);
            return cal.getTime();
        }
    }

    public static Date getDate(boolean isTH) {
        Calendar cal;
        cal = Calendar.getInstance(Locale.US); 
        
        if (isTH) {
            cal.add(Calendar.YEAR, 543);
        }

        return cal.getTime();
    }

    public static void addTime(Date date, Date time) {
        if (date != null && time != null) {
            //date.setHours(time.getHours());
            //date.setMinutes(time.getMinutes());
            Calendar c = Calendar.getInstance(Locale.US);
            c.setTime(date);
            Calendar c2 = Calendar.getInstance(Locale.US);
            c2.setTime(time);
            c.set(Calendar.HOUR_OF_DAY, c2.get(Calendar.HOUR_OF_DAY));
            c.set(Calendar.MINUTE, c2.get(Calendar.MINUTE));
        }
    }
    
    public static Date getCustomDateFormat(String strDate, String format){
        try{
            DateFormat formatter = new SimpleDateFormat(format, Locale.US);
            return (Date)formatter.parse(strDate);
        } catch (ParseException e){
            return null;
        }
    }
    
    public static String getDateTimeForGenMsgTrxStr(Date date, boolean isTH) {
        if (date == null) {
            return "";
        } else {
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(date);
            if (isTH){
                cal.add(Calendar.YEAR, 543);
            }
            return genmsgtrxFormat.format(cal.getTime());
        }
    }
    
    public static String getMySqlDateTimeStr(Date date, boolean isTH) {
        if (date == null) {
            return "";
        } else {
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(date);
            if (isTH){
                cal.add(Calendar.YEAR, 543);
            }
            return mysqlDateTimeFormat.format(cal.getTime());
        }
    }
    
    public static String getCustomStrDateFormat(Date date, String format, boolean isTH) {
        if(date == null || format == null || format.length() == 0) {
            return "";
        } else {
            SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.US);
            Calendar cal = Calendar.getInstance(Locale.US);
            cal.setTime(date);
            if (isTH){
                cal.add(Calendar.YEAR, 543);
            }
            return formatter.format(cal.getTime());
        }
    }
    
    public static String getCurrencyDateStr(boolean isTH){
        Calendar c = null;
        if(isTH){
            c = Calendar.getInstance(new Locale("th", "TH"));            
        }else{
            c = Calendar.getInstance(Locale.US);
        }
        return getDateStr(c.getTime(), isTH);
    }
    
    public static long getDiffDays(Date dateFrom, Date dateTo){
        long MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
        long diff = Math.abs(dateTo.getTime() - dateFrom.getTime());
        return diff / MILLIS_IN_DAY;
    }
    
    public static List getDateRange(Date dateFrom, Date dateTo){
        List dateL = new ArrayList();
        if(dateFrom == null){
            dateFrom = new Date();
            dateTo = new Date();
        } else if(dateTo == null){
            dateTo = new Date();
        }
        //int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
        Date currentDate = trimDate(dateFrom);
        dateTo = trimDate(dateTo);
        while(!currentDate.equals(dateTo)){
            dateL.add(currentDate);
            //currentDate = new Date(dateFrom.getTime() + MILLIS_IN_DAY);
            currentDate = addDate(currentDate, 1);
        }
        dateL.add(currentDate);
        return dateL;
    }
    
    public static boolean isEndOfMonth(Date theDate){
        Calendar cal = Calendar.getInstance();
        cal.setTime(theDate);
        return cal.get(Calendar.DATE) == cal.getActualMaximum(Calendar.DATE);
    }
    
    public static String getCurrentMonth(Date d){
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        int m = cal.get(Calendar.MONTH) + 1;
        int y = cal.get(Calendar.YEAR);
        return String.valueOf(m) + "/" + String.valueOf(y);
    }
    
    public static List<String> getMonthRange(Date d, int range){
        List<String> monthList = new ArrayList<String>();
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        int m = cal.get(Calendar.MONTH) + 1;
        int y = cal.get(Calendar.YEAR);
        
        for(int i=range; i>0; i--){
            cal.add(Calendar.MONTH, (i*-1));
            monthList.add((cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.YEAR));
            cal.add(Calendar.MONTH, i);
        }
        for(int i=0; i<=range; i++){
            cal.add(Calendar.MONTH, i);
            monthList.add((cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.YEAR));
            cal.add(Calendar.MONTH, (i*-1));
        }
        return monthList;
    }
    
    public static Date getStartDateOfMonth(Date d){
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        cal.set(Calendar.DATE, 1);
        return cal.getTime();
    }
    
    public static Date getEndDateOfMonth(Date d){
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(d);
        cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
        return cal.getTime();
    }
    
    public static void main(String args[]){
        /*List<Date> list = getDateRange(createDate(1, 9, 2009, false), createDate(10, 9, 2009, false));
        for(int i=0; i<list.size(); i++){
            Date d = list.get(i);
            System.out.println(d);
        }
        System.out.println(isEndOfMonth(createDate(29, 9, 2009, false)));
        System.out.println(getDiffDays(createDate(1, 9, 2009, false), createDate(10, 9, 2009, false)));*/
        //List<String> list = getMonthRange(createDate(1, 10, 2009, false), 10);
        //for(int i=0; i<list.size(); i++){
        //    System.out.println(list.get(i));
        //}
        //System.out.println("StartDateOfMonth = " + getStartDateOfMonth(new Date()));
        //System.out.println("EndDateOfMonth = " + getEndDateOfMonth(new Date()));
    	
    	System.out.println("createDateTime : " + createDateTime("12/03/2011 15:30", false));
    }
 
}
